/*
 * TreePath.java  0.4.0 / Oct 25, 2010
 *
 * Copyright (c) 2010 - 2011, cute4j.com and contributors.
 *
 * This software is licensed under the LGPL version 2.1 license.
 * A copy of this license is included in the file LICENSE-LGPL.txt.
 */
package com.cute4j.swing.tree;

/**
 * Tree Path.
 *
 * @author Slobodan Vrkacevic
 * @version 0.4.0
 */
public class TreePath {

// Private Fields. -------------------------------------------------------------

  private TreePath parent;
  private Object lastNode;

// Public Constructors. --------------------------------------------------------

  /**
   * Constructs new TreePath object.
   *
   * @param singlePath the single path
   */
  public TreePath(Object singlePath) {
    if (singlePath == null) {
      throw new IllegalArgumentException("Null single path");
    }
    lastNode = singlePath;
  }

  /**
   * Constructs new TreePath object.
   *
   * @param path the path
   */
  public TreePath(Object[] path) { // NOPMD
    if (path == null) {
      throw new IllegalArgumentException("Null path");
    }
    int pathLength = path.length;
    if (pathLength == 0) {
      throw new IllegalArgumentException("Empty path");
    }
    lastNode = path[pathLength - 1];
    if (pathLength > 1) {
      parent = new TreePath(path, path.length - 1);
    }
  }

// Protected Constructors. -----------------------------------------------------

  /**
   * Constructs new TreePath object.
   */
  protected TreePath() {
    // empty constructor body
  }

  /**
   * Constructs new TreePath object.
   *
   * @param path the path
   * @param length the length of the path
   */
  protected TreePath(Object[] path, int length) { // NOPMD
    lastNode = path[length - 1];
    if (length > 1) {
      parent = new TreePath(path, length - 1);
    }
  }

  /**
   * Constructs new TreePath object.
   *
   * @param parent the parent path
   * @param lastElement the last element
   */
  protected TreePath(TreePath parent, Object lastElement) {
    if (lastElement == null) {
      throw new IllegalArgumentException("Null last element");
    }
    this.parent = parent;
    lastNode = lastElement;
  }

// Public Methods. -------------------------------------------------------------

  /**
   * Returns parent path.
   *
   * @return parent path
   */
  public TreePath getParentPath() {
    return parent;
  }

  /**
   * Returns the number of nodes in the path.
   *
   * @return the number of nodes in the path
   */
  public int getPathCount() {
    int count = 0;
    for (TreePath path = this; path != null; path = path.parent) {
      count++;
    }
    return count;
  }

  /**
   * Returns array of path components.
   *
   * @return array of path component
   */
  public Object[] getPath() {
    int count = getPathCount();
    Object[] result = new Object[count--];
    for (TreePath path = this; path != null; path = path.parent) {
      result[count--] = path.lastNode;
    }
    return result;

  }

  /**
   * Returns last path component.
   *
   * @return last path component
   */
  public Object getLastPathComponent() {
    return lastNode;
  }

// Overridden Methods. ---------------------------------------------------------

  /**
   * {@inheritDoc}
   */
  public int hashCode() {
    if (lastNode != null) {
      return lastNode.hashCode();
    }
    return 0;
  }

  /**
   * {@inheritDoc}
   */
  public boolean equals(Object obj) {
    if (obj == this) {
      return true;
    }
    if ((obj != null) && (obj.getClass() == getClass())) {
      TreePath path = (TreePath)obj;
      if (getPathCount() != path.getPathCount()) {
        return false;
      }
      TreePath next = this;
      TreePath pathNext = path;
      while (next != null) {
        if (!(next.lastNode.equals(pathNext.lastNode))) {
          return false;
        }
        next = next.parent;
        pathNext = pathNext.parent;
      }
      return true;
    }
    return false;
  }

}
